#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <fstream>
using namespace std;

const int gbacklog = 10;

class HTTPServer
{
public:
    HTTPServer()
    {
    }
    HTTPServer(const uint16_t &port)
        : _listensock(-1), _port(port)
    {
    }
    ~HTTPServer()
    {
    }

    void InitServer()
    {
        // 创建套接字
        _listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listensock == -1)
        {
            cerr << "Create Socket Fail!" << endl;
            exit(2);
        }
        // 绑定
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = htonl(INADDR_ANY);
        local.sin_family = AF_INET;
        int n = bind(_listensock, (struct sockaddr *)&local, sizeof(local));
        if (n == -1)
        {
            cerr << "Bind Socket Fail!" << endl;
            exit(3);
        }
        // 设置监听状态
        int res = listen(_listensock, gbacklog);
        if (res == -1)
        {
            cerr << "Listen Socket Fail!" << endl;
            exit(4);
        }
    }

    void Start()
    {
        struct sockaddr peer;
        bzero(&peer, sizeof(peer));
        socklen_t len = sizeof(peer);
        for (;;)
        {
            // 接受新链接
            int newsock = accept(_listensock, (struct sockaddr *)&peer, &len);
            if (newsock == -1)
            {
                cerr << "Accept Socket Fail!" << endl;
                // exit(5);
                continue; // 继续拉客
            }
            // 接受IO请求的内容  子进程来做
            pid_t pid = fork();
            if (pid == 0)
            {
                // 子进程
                close(_listensock);
                // 孙子进程recv
                if (fork() > 0)
                {
                    exit(0);
                }
                char buffer[4096];
                ssize_t n = recv(newsock, buffer, sizeof(buffer), 0);
                if (n > 0)
                {
                    buffer[n] = 0;
                }
                cout << "------------------------- HTTP Request Begin -------------------------" << endl;
                cout << buffer << endl;
                cout << "------------------------- HTTP  Request  End -------------------------" << endl;
#define PAGE "index.html"
                ifstream in(PAGE);
                if (in.is_open())
                {
                    in.seekg(0, in.end);
                    int len = in.tellg();
                    in.seekg(0, in.beg);
                    char *file = new char[len];
                    in.read(file, len);
                    in.close();

                    // 构建HTTP响应  客户端只能看到响应的正文？
                    // string status_line = "HTTP/1.1 200 OK\r\n";
                    // string response_header = "Content_Length: " + to_string(len) + "\r\n";
                    // string blank = "\r\n";
                    // string response_text = file; // 响应正文
                    // string response = status_line + response_header + blank + response_text;

                    //构建重定向响应
                    string status_line = "HTTP/1.1 302 Temporary Redirect\r\n";//状态行
                    string response_header = "Location: https://gitee.com/little-bit-tang-chen";//重定向url
                    string blank = "\r\n";
                    string response = status_line + response_header + blank;

                    // send
                    send(newsock, response.c_str(), response.size(), 0);
                    delete[] file;
                }
                close(newsock);
                exit(0);
            }
            close(newsock);
            waitpid(pid, nullptr, 0); // 阻塞等待
        }
    }

public:
    int _listensock;
    uint16_t _port;
};